﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LM.InterfacesFabricas.Interfaces.Repositorios;
using LM.Negocio.Objetos;

namespace LM.Negocio.Validadores
{
    public class ValidadorDeCliente : ValidadorAbastrato
    {
        private Cliente _objetoValidado;

        private IRepositorioDeConsultaDeObjetos<Cliente> _repositorioDeCliente;

        public ValidadorDeCliente( IRepositorioDeConsultaDeObjetos<Cliente> repositorioDeCliente )
        {
            if ( repositorioDeCliente == null )
            {
                throw new ArgumentNullException( "repositorioDeCliente" );
            }

            _repositorioDeCliente = repositorioDeCliente;
        }

        /// <summary>
        /// Realiza as verificações necessárias, para identificar irregularidades nos dados.
        /// </summary>
        /// <param name="cliente">Cliente a ser validado.</param>
        public void ValideCadastro( Cliente cliente)
        {
            if ( cliente == null )
            {
                throw new ArgumentException( "cliente" );
            }

            _objetoValidado = cliente;
            base.LimpeInconsistencias();

            ValideCodigoNaoInformado();
            ValideNomeNaoInformado();
            ValideCpfNaoInformado();
            ValideCnhNaoInformado();
            ValideTipoClienteNaoInformado();
            ValideClienteJaCadastrado();

            base.GarantaSucesso();
        }

        public void ValideAtualizacao( Cliente cliente)
        {
            if ( cliente == null )
            {
                throw new ArgumentException( "cliente" );
            }

            _objetoValidado = cliente;
            base.LimpeInconsistencias();

            ValideCodigoNaoInformado();
            ValideNomeNaoInformado();
            ValideCpfNaoInformado();
            ValideCnhNaoInformado();
            ValideTipoClienteNaoInformado();
            ValideClienteNaoCadastrado();

            base.GarantaSucesso();
        }

        public void ValideExclusao( Cliente cliente)
        {
            if ( cliente == null )
            {
                throw new ArgumentException( "cliente" );
            }

            _objetoValidado = cliente;
            base.LimpeInconsistencias();

            ValideClienteNaoCadastrado();

            base.GarantaSucesso();
        }

        #region Métodos de Validação de cliente

        private void ValideCodigoNaoInformado()
        {
            if (_objetoValidado.Codigo == 0)
            {
                AdicioneInconsistencia("Código não informado.");
            }
        }

        private void ValideNomeNaoInformado()
        {
            if (String.IsNullOrWhiteSpace(_objetoValidado.Nome))
            {
                AdicioneInconsistencia("Nome não informado.");
            }
        }

        private void ValideCpfNaoInformado()
        {
            if (String.IsNullOrWhiteSpace(_objetoValidado.Cpf))
            {
                AdicioneInconsistencia("Cpf não informado.");
            }
        }

        private void ValideCnhNaoInformado()
        {
            if (String.IsNullOrWhiteSpace(_objetoValidado.Cnh))
            {
                AdicioneInconsistencia("Cnh não informado.");
            }
        }

        private void ValideTipoClienteNaoInformado()
        {
            if (_objetoValidado.TipoDoCliente == 0)
            {
                AdicioneInconsistencia("Por favor selecione um tipo para o cliente.");
            }
        }

        #endregion

        #region Métodos de Garantia

        private bool ClienteJaCadastrado()
        {
            return _repositorioDeCliente.Consulte(m => m.Codigo == _objetoValidado.Codigo).Any();
        }

        private void ValideClienteJaCadastrado()
        {
            if (ClienteJaCadastrado())
            {
                AdicioneInconsistencia("Já existe um Cliente cadastrada com o código {0}.", _objetoValidado.Codigo);
            }
        }

        /// <summary>
        /// Verifica no banco de dados se um determinado objeto/codigo/guid,
        /// está ou não cadastrado no banco, impedindo o prosseguimento de cadastro
        /// caso ja exista.
        /// </summary>
        private void ValideClienteNaoCadastrado()
        {
            if (!ClienteJaCadastrado())
            {
                AdicioneInconsistencia("Cliente com o código {0} não cadastrada.", _objetoValidado.Codigo);
            }
        }

        #endregion
    }
}
